package com.example.concurrentprogramming8016.blockingqueue;

import java.util.concurrent.BlockingQueue;
import java.util.concurrent.DelayQueue;
import java.util.concurrent.Delayed;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicInteger;

/**
 * @author liyanhao
 * @Date 2023-01-07 22:22
 * 先让主线程往delayed添加首个任务，
 * 任务之间的启动间隔1~2秒之间，
 * 每个任务的执行时间固定为2秒
 */
public class DelayTask implements Delayed {

    private static long currentTime = System.currentTimeMillis();
    protected final String taskName;
    protected final int timeCost;
    protected final long scheduleTime;
    protected static final AtomicInteger taskCount = new AtomicInteger(0);
    //定时任务之间的启动时间间隔在1~2秒，timecount表示处理此任务需要的时间 本实例中为2秒


    public DelayTask(String taskName, int timeCost) {
        this.taskName = taskName;
        this.timeCost = timeCost;
        taskCount.incrementAndGet();
        currentTime += 1000 + (long) (Math.random() * 1000);
        scheduleTime = currentTime;
    }

    @Override
    public int compareTo(Delayed o) {
        return (int) (this.scheduleTime - ((DelayTask) o).scheduleTime);
    }

    @Override
    public long getDelay(TimeUnit unit) {
        long expoireationTime = scheduleTime - System.currentTimeMillis();
        return unit.convert(expoireationTime, TimeUnit.MILLISECONDS);
    }

    public void exectask() {
        long startTime = System.currentTimeMillis();
        System.out.println("Task " + taskName + ":schedule_start_time=" + scheduleTime +
                ",real start time=" + startTime + ",delay=" + (startTime - scheduleTime));
        try {
            TimeUnit.MILLISECONDS.sleep(timeCost);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
}

class DelayTaskConsumer extends Thread {
    private final BlockingQueue<DelayTask> queue;

    public DelayTaskConsumer(BlockingQueue<DelayTask> queue) {
        this.queue = queue;
    }

    @Override
    public void run() {
        DelayTask task = null;
        try {
            for (; ; ) {
                task = queue.take();
                task.exectask();
                DelayTask.taskCount.decrementAndGet();
            }
        } catch (InterruptedException e) {
            System.out.println(getName() + " finished");
        }
    }
}

class DelayedQueueTest {
    public static void main(String[] args) {
        DelayQueue<DelayTask> delayQueue = new DelayQueue<DelayTask>();
        for (int i = 0; i < 10; i++) {
            delayQueue.put(new DelayTask("work " + i, 2000));
        }
        ThreadGroup consumers = new ThreadGroup("Consumers");

        for (int i = 0; i < 1; i++) {
            new Thread(consumers,new DelayTaskConsumer(delayQueue)).start();
        }
        while (DelayTask.taskCount.get() > 0) {
            try {
                TimeUnit.MILLISECONDS.sleep(50);
            } catch (InterruptedException e) {
                throw new RuntimeException(e);
            }
        }
        consumers.interrupt();
        System.out.println("Main Thread finished");
    }
}
